
// preprocessor.h

// This file is an extract from some files (like ct_if.hpp) of the huge Boost library (35 Megabyte)
// modified, shortened and compacted to one file by ElmueSoft (www.elmue.de.vu  or  kickme.to/elmue)



// -------------------------------------------------------------------
// Boost.Function library

// Copyright (C) 2001-2003 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.

// For more information, see http://www.boost.org
// -------------------------------------------------------------------


#if !defined(PREPROCESSOR_H)
#define PREPROCESSOR_H


// turn off MS Visual Studio warning: "Identifier was truncated to '255' characters in the debug information"
#pragma warning( disable : 4786 )


// Note:
// Older versions of compilers do not support partial template specialization
// In this case a workaround is necessary

#if   _MSC_VER == 1200 // Visual Studio 6.0
  #define PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE   0

#elif _MSC_VER == 1300 // Visual Studio 7.0 (.NET)
  #define PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE   0

#elif _MSC_VER == 1310 // Visual Studio 7.1 (.NET 2003)
  #define PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE   1

#elif _MSC_VER == 1400 // Visual Studio 8.0 (.NET 2005)
  #define PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE   1

#elif _MSC_VER == 1500 // Visual Studio 9.0
  #define PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE   1

#else // Unknown Compiler (please set the value manually to 0 or 1)
  #error Unknown compiler : insert 0 or 1 in the next line and comment out this line !
  #define PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE   ?
#endif

// *********** <PREPROCESSOR MACROS> ***************


// UNUSABLE is used as a dummy replacement for functions returning void
// Needed for compilers not supporting partial template specialization
// (like MS Visual Studio 6)

#define UNUSABLE \
cPreProcessor::unusable*


// IS_VOID returns true if class T == void, otherwise false

#define IS_VOID(T) \
cPreProcessor::is_void<T>::value


// IS_USABLE returns 0 if class T == cPreProcessor::unusable*, otherwise 1

#define IS_USABLE(T) \
cPreProcessor::is_usable<T>::value


// CLASS_SWITCH returns class A if condition == true, class B if condition == false

#define CLASS_SWITCH(condition, A, B) \
cPreProcessor::select_switch<condition, A, B>::value



// *********** <PREPROCESSOR SWITCHES> ***************

struct cPreProcessor
{
    // ################  unusable  #################

    struct unusable
    {
        // empty structure
    };

    // ################  is_void  #################

    template <typename T>
    struct is_void
    { enum { value = false }; };

    // Specialization of is_void for T == void
    template <>
    struct is_void<void>
    { enum { value = true }; };

    // ################  is_usable  #################

    template <typename T>
    struct is_usable
    { enum { value = 1 }; };

    // Specialization of is_usable for T == unusable*
    template <>
    struct is_usable<unusable*>
    { enum { value = 0 }; };

    // ################  select_switch  #################

#if PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE

    // for newer compilers (e.g. Visual Studio 7.1 = Visual Studio .NET 2003)

    template<int condition, class A, class B>
    // partial specialization for condition == illegal value
    struct select_switch
    {
        typedef typename UNUSABLE value;
    };

    // partial specialization for condition == true
    template<class A, class B>
    struct select_switch<true, A, B>
    {
        typedef typename A value;
    };

    // partial specialization for condition == false
    template<class A, class B>
    struct select_switch<false, A, B>
    {
        typedef typename B value;
    };

#else //  !PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE

    // for older compilers: (e.g. Visual Studio 6.0 and 7.0)
    // the following has to be that awkward because lots of old compilers
    // do not support partial template specialization

    struct switch_true
    {
        template<class A, class B>
        struct class_switch
        { typedef  A  ret_class; };
    };

    struct switch_false
    {
        template<class A, class B>
        struct class_switch
        { typedef  B  ret_class; };
    };

    template<int condition>
    struct condition_switch
    { typedef  switch_true  selector; };

    // Specialization of condition_switch for condition == false
    template <>
    struct condition_switch<false>
    { typedef  switch_false  selector; };


    template<int condition, class A, class B>
    struct select_switch
    {
        typedef  condition_switch<condition>::selector    Selector;
        typedef  Selector::class_switch<A, B>::ret_class  value;
    };

#endif // PARTIAL_TEMPLATE_SPECIALIZATION_AVAILABLE

};

#endif // PREPROCESSOR_H
